using Beauty.Net.Cache.Core;
using FreeRedis;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace Beauty.Net.Cache;

/// <summary>
/// 缓存服务依赖注入扩展
/// </summary>
public static class CacheServiceCollectionExtensions
{
    /// <summary>
    /// 添加缓存服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="configureOptions">配置选项</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddCacheService(
        this IServiceCollection services,
        Action<CacheOptions>? configureOptions = null)
    {
        // 注册配置选项
        if (configureOptions != null)
        {
            services.Configure(configureOptions);
        }
        else
        {
            services.Configure<CacheOptions>(options => { });
        }

        // 注册内存缓存（无论使用哪种缓存类型都需要，作为后备或直接使用）
        services.AddMemoryCache();

        // 根据配置注册相应的缓存服务实现
        services.AddSingleton<ICacheService>(provider =>
        {
            var options = provider.GetRequiredService<IOptions<CacheOptions>>().Value;
            
            switch (options.CacheType)
            {
                case CacheType.Redis:
                    if (string.IsNullOrEmpty(options.RedisConnectionString))
                    {
                        throw new ArgumentNullException(nameof(options.RedisConnectionString), "Redis连接字符串不能为空");
                    }
                    
                    var redisClient = new RedisClient(options.RedisConnectionString);
                    // 配置Redis客户端
                    redisClient.Serialize = obj => 
                    {
                        return System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(obj);
                    };
                    redisClient.Deserialize = (bytes, type) =>
                    {
                        return System.Text.Json.JsonSerializer.Deserialize(bytes, type);
                    };
                    
                    return new RedisCacheService(redisClient);
                
                case CacheType.Memory:
                default:
                    var memoryCache = provider.GetRequiredService<IMemoryCache>();
                    return new MemoryCacheService(memoryCache);
            }
        });

        return services;
    }

    /// <summary>
    /// 添加Redis缓存服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="connectionString">Redis连接字符串</param>
    /// <param name="defaultExpireMinutes">默认过期时间（分钟）</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddRedisCacheService(
        this IServiceCollection services,
        string connectionString,
        int defaultExpireMinutes = 30)
    {
        return services.AddCacheService(options =>
        {
            options.CacheType = CacheType.Redis;
            options.RedisConnectionString = connectionString;
            options.DefaultExpireMinutes = defaultExpireMinutes;
        });
    }

    /// <summary>
    /// 添加内存缓存服务
    /// </summary>
    /// <param name="services">服务集合</param>
    /// <param name="defaultExpireMinutes">默认过期时间（分钟）</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddMemoryCacheService(
        this IServiceCollection services,
        int defaultExpireMinutes = 30)
    {
        return services.AddCacheService(options =>
        {
            options.CacheType = CacheType.Memory;
            options.DefaultExpireMinutes = defaultExpireMinutes;
        });
    }
}